package com.frankle.mybatisplusgenerator.controller;

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ResourceBundle;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.BeetlTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import com.frankle.mybatisplusgenerator.App;
import com.frankle.mybatisplusgenerator.constant.StageView;
import com.frankle.mybatisplusgenerator.constant.TemplateEngine;
import com.frankle.mybatisplusgenerator.utils.AlertUtils;
import com.frankle.mybatisplusgenerator.utils.I18N;
import com.frankle.mybatisplusgenerator.utils.StringUtils;
import com.frankle.mybatisplusgenerator.utils.ViewUtils;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Tab;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.RowConstraints;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;

public class MainViewController implements Initializable {
	
	@FXML
	private Tab tab_1;
	@FXML
	private Tab tab_2;
	@FXML
	private Tab tab_3;
	@FXML
	private Tab tab_4;
	@FXML
	private Tab tab_5;
	@FXML
	private Tab tab_6;
	@FXML
	private Menu m_file;
	@FXML
	private Menu m_settings;
	@FXML
	private Menu m_help;
	@FXML
	private MenuItem mi_file_generate;
	@FXML
	private MenuItem mi_file_exit;
	@FXML
	private MenuItem mi_settings_options;
	@FXML
	private MenuItem mi_help_about;
	@FXML
	private MenuItem mi_help_website;
	
	/* 数据源配置 */
	@FXML private Label lb_config_database_type;
	@FXML private ComboBox<DbType> config_database_type;
	
	@FXML private Label lb_config_database_driver_jar_path;
	@FXML private TextField config_database_driver_jar_path;
	@FXML private RowConstraints rc_driver_jar_path;
	
	@FXML private Button btn_choose_driver_jar;
	
	@FXML private Label lb_config_database_driver_class_name;
	@FXML private TextField config_database_driver_class_name;
	@FXML private RowConstraints rc_driver_class_name;
	
	@FXML private Label lb_config_database_url;
	@FXML private TextField config_database_url;
	
	@FXML private Label lb_config_database_postgreSQL_schema;
	@FXML private TextField config_database_postgreSQL_schema;
	@FXML private RowConstraints rc_postgreSQL_schema;
	
	@FXML private Label lb_config_database_username;
	@FXML private TextField config_database_username;
	
	@FXML private Label lb_config_database_password;
	@FXML private TextField config_database_password;
	
	@FXML private Button btn_test_connect;
	
	private static double ROW_HEIGHT = 46.0;
	
	private static Driver driver = null;
	private static DbType dbType = null;
	
	/* 全局配置 */
	@FXML
	private Button btn_global_choose_output;
	/**
	 * 输出路径
	 */
	@FXML private Label lb_config_global_output;
	@FXML private TextField config_global_output;
	/**
	 * 作者
	 */
	@FXML private Label lb_config_global_author;
	@FXML private TextField config_global_author;
	/**
	 * 日期类型
	 */
	@FXML private Label lb_config_global_datetype;
	@FXML private TextField config_global_datetype;
	/**
	 * 是否开启ActiveRecord
	 */
	@FXML private Label lb_config_global_activerecord;
	@FXML private CheckBox config_global_activerecord;
	/**
	 * 实体类名称格式
	 */
	@FXML private Label lb_config_global_entityname;
	@FXML private TextField config_global_entityname;
	/**
	 * Controller类名称格式
	 */
	@FXML private Label lb_config_global_controllername;
	@FXML private TextField config_global_controllername;
	/**
	 * service类名称格式
	 */
	@FXML private Label lb_config_global_servicename;
	@FXML private TextField config_global_servicename;
	/**
	 * serviceImpl类名称格式
	 */
	@FXML private Label lb_config_global_serviceimplname;
	@FXML private TextField config_global_serviceimplname;
	/**
	 * mapper类名称格式
	 */
	@FXML private Label lb_config_global_mappername;
	@FXML private TextField config_global_mappername;
	/**
	 * xml类名称格式
	 */
	@FXML private Label lb_config_global_xmlname;
	@FXML private TextField config_global_xmlname;
	/**
	 * 实体类Id生成策略
	 */
	@FXML private Label lb_config_global_idtype;
	@FXML private TextField config_global_idtype;
	/**
	 * 是否覆盖文件
	 */
	@FXML private Label lb_config_global_fileoverride;
	@FXML private CheckBox config_global_fileoverride;
	/**
	 * 是否生成后打开文件夹
	 */
	@FXML private Label lb_config_global_open;
	@FXML private CheckBox config_global_open;
	/**
	 * 是否生成swagger
	 */
	@FXML private Label lb_config_global_swagger2;
	@FXML private CheckBox config_global_swagger2;
	/**
	 * 是否生成BaseColumnList
	 */
	@FXML private Label lb_config_global_basecolumnlist;
	@FXML private CheckBox config_global_basecolumnlist;
	/**
	 * 是否生成BaseResultMap
	 */
	@FXML private Label lb_config_global_baseresultmap;
	@FXML private CheckBox config_global_baseresultmap;
	/**
	 * 是否缓存
	 */
	@FXML private Label lb_config_global_enablecache;
	@FXML private CheckBox config_global_enablecache;
	/**
	 * 是否使用Kotlin
	 */
	@FXML private Label lb_config_global_kotlin;
	@FXML private CheckBox config_global_kotlin;
	
	@FXML private Label lb_config_global_id_type;
	@FXML private ToggleGroup tg_id_type;
	@FXML private RadioButton id_type_auto;
	@FXML private RadioButton id_type_none;
	@FXML private RadioButton id_type_input;
	@FXML private RadioButton id_type_assign_id;
	@FXML private RadioButton id_type_assign_uuid;
	
	@FXML private Label lb_config_global_date_type;
	@FXML private ToggleGroup tg_date_type;
	@FXML private RadioButton date_type_timepack;
	@FXML private RadioButton date_type_onlydate;
	@FXML private RadioButton date_type_sqlpack;
	
	@FXML private Button btn_restore_global_config;
	
	/* 包名配置 */
	@FXML private Label lb_config_packageInfo_parent;
	@FXML private TextField config_packageInfo_parent;
	
	@FXML private Label lb_config_packageInfo_module;
	@FXML private TextField config_packageInfo_module;
	
	@FXML private Label lb_config_packageInfo_entity;
	@FXML private TextField config_packageInfo_entity;
	
	@FXML private Label lb_config_packageInfo_controller;
	@FXML private TextField config_packageInfo_controller;
	
	@FXML private Label lb_config_packageInfo_service;
	@FXML private TextField config_packageInfo_service;
	
	@FXML private Label lb_config_packageInfo_serviceimpl;
	@FXML private TextField config_packageInfo_serviceimpl;
	
	@FXML private Label lb_config_packageInfo_mapper;
	@FXML private TextField config_packageInfo_mapper;
	
	@FXML private Label lb_config_packageInfo_xml;
	@FXML private TextField config_packageInfo_xml;
	
	@FXML private Button btn_restore_package_config;
	
	/* 策略配置 */
	@FXML private Button btn_restore_strategy_config;
	@FXML private Label lb_cfg_strategy_capital_mode;
	@FXML private CheckBox cfg_strategy_capital_mode;
	
	@FXML private Label lb_cfg_strategy_naming;
	@FXML private ToggleGroup tg_naming;
	@FXML private RadioButton naming_no_change;
	@FXML private RadioButton naming_underline_to_camel;
	
	@FXML private Label lb_cfg_strategy_column_naming;
	@FXML private ToggleGroup tg_column_naming;
	@FXML private RadioButton column_naming_no_change;
	@FXML private RadioButton column_naming_underline_to_camel;
	
	@FXML private Label lb_cfg_strategy_include;
	@FXML private TextArea cfg_strategy_include;
	
	@FXML private Label lb_cfg_strategy_exclude;
	@FXML private TextArea cfg_strategy_exclude;
	
	@FXML private Label lb_cfg_strategy_skip_view;
	@FXML private CheckBox cfg_strategy_skip_view;
	
	@FXML private Label lb_cfg_strategy_table_prefix;
	@FXML private TextField cfg_strategy_table_prefix;
	
	@FXML private Label lb_cfg_strategy_field_prefix;
	@FXML private TextField cfg_strategy_field_prefix;
	
	@FXML private Label lb_cfg_strategy_super_entity_class;
	@FXML private TextField cfg_strategy_super_entity_class;
	
	@FXML private Label lb_cfg_strategy_super_entity_columns;
	@FXML private TextArea cfg_strategy_super_entity_columns;
	
	@FXML private Label lb_cfg_strategy_boolean_column_remove_is_prefix;
	@FXML private CheckBox cfg_strategy_boolean_column_remove_is_prefix;
	
	@FXML private Label lb_cfg_strategy_builder_mode;
	@FXML private CheckBox cfg_strategy_builder_mode;
	
	@FXML private Label lb_cfg_strategy_column_constant;
	@FXML private CheckBox cfg_strategy_column_constant;
	
	@FXML private Label lb_cfg_strategy_lombok_mode;
	@FXML private CheckBox cfg_strategy_lombok_mode;
	
	@FXML private Label lb_cfg_strategy_table_field_annotation;
	@FXML private CheckBox cfg_strategy_table_field_annotation;
	
	@FXML private Label lb_cfg_strategy_logic_delete_field;
	@FXML private TextField cfg_strategy_logic_delete_field;
	
	@FXML private Label lb_cfg_strategy_version_field;
	@FXML private TextField cfg_strategy_version_field;
	
	@FXML private Label lb_cfg_strategy_restcontroller_style;
	@FXML private CheckBox cfg_strategy_restcontroller_style;
	
	@FXML private Label lb_cfg_strategy_super_controller_class;
	@FXML private TextField cfg_strategy_super_controller_class;
	
	@FXML private Label lb_cfg_strategy_mapping_hyphen_style;
	@FXML private CheckBox cfg_strategy_mapping_hyphen_style;
	
	@FXML private Label lb_cfg_strategy_super_service_class;
	@FXML private TextField cfg_strategy_super_service_class;
	
	@FXML private Label lb_cfg_strategy_super_serviceimpl_class;
	@FXML private TextField cfg_strategy_super_serviceimpl_class;
	
	@FXML private Label lb_cfg_strategy_super_mapper_class;
	@FXML private TextField cfg_strategy_super_mapper_class;
	/* 注入配置 */
	
	/* 模板配置 */
	@FXML private Label lb_cfg_template_custom_template;
	@FXML private CheckBox cfg_template_custom_template;
	
	@FXML private Label lb_cfg_template_engine;
	@FXML private ToggleGroup tg_template_engine;
	@FXML private RadioButton template_engine_freemarker;
	@FXML private RadioButton template_engine_velocity;
	@FXML private RadioButton template_engine_beelt;
	
	@FXML private Label lb_cfg_template_entity;
	@FXML private TextField cfg_template_entity;
	
	@FXML private Label lb_cfg_template_entity_kt;
	@FXML private TextField cfg_template_entity_kt;
	
	@FXML private Label lb_cfg_template_controller;
	@FXML private TextField cfg_template_controller;
	
	@FXML private Label lb_cfg_template_service;
	@FXML private TextField cfg_template_service;
	
	@FXML private Label lb_cfg_template_serviceimpl;
	@FXML private TextField cfg_template_serviceimpl;
	
	@FXML private Label lb_cfg_template_mapper;
	@FXML private TextField cfg_template_mapper;
	
	@FXML private Label lb_cfg_template_xml;
	@FXML private TextField cfg_template_xml;
	
	@FXML private Button btn_restore_template_config;
	
	@FXML private Label lb_status;
	
	private static PackageConfig pkgCfg = new PackageConfig();
	private static GlobalConfig gbCfg = new GlobalConfig();
	private static StrategyConfig stgCfg = new StrategyConfig();
	
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		tab_1.textProperty().bind(I18N.createStringBinding("config.dataSource"));
		tab_2.textProperty().bind(I18N.createStringBinding("config.global"));
		tab_3.textProperty().bind(I18N.createStringBinding("config.strategy"));
		tab_4.textProperty().bind(I18N.createStringBinding("config.inject"));
		tab_5.textProperty().bind(I18N.createStringBinding("config.packageInfo"));
		tab_6.textProperty().bind(I18N.createStringBinding("config.template"));
		
		m_file.textProperty().bind(I18N.createStringBinding("menu.file"));
		m_settings.textProperty().bind(I18N.createStringBinding("menu.settings"));
		m_help.textProperty().bind(I18N.createStringBinding("menu.help"));
		
		mi_file_generate.textProperty().bind(I18N.createStringBinding("menu.file.generate"));
		mi_file_exit.textProperty().bind(I18N.createStringBinding("menu.file.exit"));
		mi_settings_options.textProperty().bind(I18N.createStringBinding("menu.settings.options"));
		mi_help_about.textProperty().bind(I18N.createStringBinding("menu.help.about"));
		mi_help_website.textProperty().bind(I18N.createStringBinding("menu.help.website"));
		
		/* 数据源 */
		DbType[] values = DbType.values();
		config_database_type.setItems(FXCollections.observableArrayList(values));
		lb_config_database_type.textProperty().bind(I18N.createStringBinding("label.databaseType"));
		config_database_type.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<DbType>() {

			@Override
			public void changed(ObservableValue<? extends DbType> observable, DbType oldValue, DbType newValue) {
				
				showCustomDriverField(DbType.OTHER.equals(newValue));
				showPostgreSchemaField(DbType.POSTGRE_SQL.equals(newValue));
				
			}
		});
		
		lb_config_database_driver_jar_path.textProperty().bind(I18N.createStringBinding("label.driver_jar_path"));
		lb_config_database_driver_class_name.textProperty().bind(I18N.createStringBinding("label.driver_class_name"));
		
		lb_config_database_url.textProperty().bind(I18N.createStringBinding("label.url"));
		lb_config_database_username.textProperty().bind(I18N.createStringBinding("label.username"));
		lb_config_database_password.textProperty().bind(I18N.createStringBinding("label.password"));
		
		btn_test_connect.textProperty().bind(I18N.createStringBinding("action.test_connect"));
		
		showCustomDriverField(false);
		showPostgreSchemaField(false);
		
		id_type_auto.setUserData(IdType.AUTO.toString());
		id_type_none.setUserData(IdType.NONE.toString());
		id_type_input.setUserData(IdType.INPUT.toString());
		id_type_assign_id.setUserData(IdType.ASSIGN_ID.toString());
		id_type_assign_uuid.setUserData(IdType.ASSIGN_UUID.toString());
		
		date_type_timepack.setUserData(DateType.TIME_PACK.toString());
		date_type_onlydate.setUserData(DateType.ONLY_DATE.toString());
		date_type_sqlpack.setUserData(DateType.SQL_PACK.toString());
		
		/* 全局配置 */
		btn_global_choose_output.setTooltip(I18N.createTooltipBindings("tooltip.choose_output_dir"));
		
		lb_config_global_activerecord.textProperty().bind(I18N.createStringBinding("label.activerecord"));
		lb_config_global_basecolumnlist.textProperty().bind(I18N.createStringBinding("label.basecolumnlist"));
		lb_config_global_baseresultmap.textProperty().bind(I18N.createStringBinding("label.baseresultmap"));
		lb_config_global_enablecache.textProperty().bind(I18N.createStringBinding("label.enablecache"));
		lb_config_global_fileoverride.textProperty().bind(I18N.createStringBinding("label.fileoverride"));
		lb_config_global_id_type.textProperty().bind(I18N.createStringBinding("label.id_type"));
		lb_config_global_date_type.textProperty().bind(I18N.createStringBinding("label.date_type"));
		lb_config_global_open.textProperty().bind(I18N.createStringBinding("label.open"));
		lb_config_global_kotlin.textProperty().bind(I18N.createStringBinding("label.kotlin"));
		lb_config_global_swagger2.textProperty().bind(I18N.createStringBinding("label.swagger2"));
		lb_config_global_author.textProperty().bind(I18N.createStringBinding("label.author"));
		lb_config_global_controllername.textProperty().bind(I18N.createStringBinding("label.controllername"));
		lb_config_global_entityname.textProperty().bind(I18N.createStringBinding("label.entityname"));
		lb_config_global_mappername.textProperty().bind(I18N.createStringBinding("label.mappername"));
		lb_config_global_output.textProperty().bind(I18N.createStringBinding("label.output_dir"));
		lb_config_global_serviceimplname.textProperty().bind(I18N.createStringBinding("label.serviceimplname"));
		lb_config_global_servicename.textProperty().bind(I18N.createStringBinding("label.servicename"));
		lb_config_global_xmlname.textProperty().bind(I18N.createStringBinding("label.xmlname"));
		btn_restore_global_config.textProperty().bind(I18N.createStringBinding("action.restore_default"));
		initGlobalConfig();
		
		lb_config_packageInfo_parent.textProperty().bind(I18N.createStringBinding("label.parent"));
		lb_config_packageInfo_module.textProperty().bind(I18N.createStringBinding("label.module"));
		lb_config_packageInfo_entity.textProperty().bind(I18N.createStringBinding("label.entity"));
		lb_config_packageInfo_controller.textProperty().bind(I18N.createStringBinding("label.controller"));
		lb_config_packageInfo_service.textProperty().bind(I18N.createStringBinding("label.service"));
		lb_config_packageInfo_serviceimpl.textProperty().bind(I18N.createStringBinding("label.serviceimpl"));
		lb_config_packageInfo_mapper.textProperty().bind(I18N.createStringBinding("label.mapper"));
		lb_config_packageInfo_xml.textProperty().bind(I18N.createStringBinding("label.xml"));
		btn_restore_package_config.textProperty().bind(I18N.createStringBinding("action.restore_default"));
		initPackageConfig();
		
		naming_no_change.textProperty().bind(I18N.createStringBinding("label.no_change"));
		naming_underline_to_camel.textProperty().bind(I18N.createStringBinding("label.underline_to_camel"));
		column_naming_no_change.textProperty().bind(I18N.createStringBinding("label.no_change"));
		column_naming_underline_to_camel.textProperty().bind(I18N.createStringBinding("label.underline_to_camel"));
		lb_cfg_strategy_boolean_column_remove_is_prefix.textProperty().bind(I18N.createStringBinding("label.boolean_column_remove_is_prefix"));
		lb_cfg_strategy_builder_mode.textProperty().bind(I18N.createStringBinding("label.builder_mode"));
		lb_cfg_strategy_capital_mode.textProperty().bind(I18N.createStringBinding("label.capital_mode"));
		lb_cfg_strategy_column_constant.textProperty().bind(I18N.createStringBinding("label.column_constant"));
		lb_cfg_strategy_column_naming.textProperty().bind(I18N.createStringBinding("label.column_naming"));
		lb_cfg_strategy_exclude.textProperty().bind(I18N.createStringBinding("label.exclude"));
		lb_cfg_strategy_field_prefix.textProperty().bind(I18N.createStringBinding("label.field_prefix"));
		lb_cfg_strategy_include.textProperty().bind(I18N.createStringBinding("label.include"));
		lb_cfg_strategy_logic_delete_field.textProperty().bind(I18N.createStringBinding("label.logic_delete_field"));
		lb_cfg_strategy_lombok_mode.textProperty().bind(I18N.createStringBinding("label.lombok_mode"));
		lb_cfg_strategy_mapping_hyphen_style.textProperty().bind(I18N.createStringBinding("label.mapping_hyphen_style"));
		lb_cfg_strategy_naming.textProperty().bind(I18N.createStringBinding("label.naming"));
		lb_cfg_strategy_restcontroller_style.textProperty().bind(I18N.createStringBinding("label.restcontroller_style"));
		lb_cfg_strategy_skip_view.textProperty().bind(I18N.createStringBinding("label.skip_view"));
		lb_cfg_strategy_super_controller_class.textProperty().bind(I18N.createStringBinding("label.super_controller_class"));
		lb_cfg_strategy_super_entity_class.textProperty().bind(I18N.createStringBinding("label.super_entity_class"));
		lb_cfg_strategy_super_entity_columns.textProperty().bind(I18N.createStringBinding("label.super_entity_columns"));
		lb_cfg_strategy_super_mapper_class.textProperty().bind(I18N.createStringBinding("label.super_mapper_class"));
		lb_cfg_strategy_super_service_class.textProperty().bind(I18N.createStringBinding("label.super_service_class"));
		lb_cfg_strategy_super_serviceimpl_class.textProperty().bind(I18N.createStringBinding("label.super_serviceimpl_class"));
		lb_cfg_strategy_table_field_annotation.textProperty().bind(I18N.createStringBinding("label.table_field_annotation"));
		lb_cfg_strategy_table_prefix.textProperty().bind(I18N.createStringBinding("label.table_prefix"));
		lb_cfg_strategy_version_field.textProperty().bind(I18N.createStringBinding("label.version_field"));
		btn_restore_strategy_config.textProperty().bind(I18N.createStringBinding("action.restore_default"));
		initStrategyConfig();
		
		lb_cfg_template_controller.textProperty().bind(I18N.createStringBinding("label.template.controller"));
		lb_cfg_template_entity.textProperty().bind(I18N.createStringBinding("label.template.entity"));
		lb_cfg_template_entity_kt.textProperty().bind(I18N.createStringBinding("label.template.entity_kt"));
		lb_cfg_template_service.textProperty().bind(I18N.createStringBinding("label.template.service"));
		lb_cfg_template_serviceimpl.textProperty().bind(I18N.createStringBinding("label.template.serviceimpl"));
		lb_cfg_template_mapper.textProperty().bind(I18N.createStringBinding("label.template.mapper"));
		lb_cfg_template_xml.textProperty().bind(I18N.createStringBinding("label.template.xml"));
		btn_restore_template_config.textProperty().bind(I18N.createStringBinding("action.restore_default"));
		initTemplateConfig();
		
		initOptionConfig();
	}

	/**
	 * 显示选项
	 * @author Frankle
	 * @date 2020年5月20日
	 */
	@FXML
	public void showOptions() {
		ViewUtils.showView(StageView.OPTIONS_VIEW, false, true);
	}
	
	@FXML
	public void showAbout() {
		ViewUtils.showView(StageView.ABOUT_VIEW, false, true);
	}
	
	@FXML
	public void gotoWebsite() {
		try {
			Desktop.getDesktop().browse(new URI("https://mp.baomidou.com/"));
		} catch (IOException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 选择输出目录
	 * @author Frankle
	 * @date 2020年5月21日
	 */
	@FXML
	public void chooseOutputDir() {
		DirectoryChooser dc = new DirectoryChooser();
		dc.setInitialDirectory(new File(gbCfg.getOutputDir()));
		File file = dc.showDialog(App.STAGE_MAP.get(StageView.MAIN_VIEW));
		if(file != null) {
			config_global_output.setText(file.getAbsolutePath());
		}
	}
	
	/**
	 * 选择驱动jar
	 * @author Frankle
	 * @date 2020年5月25日
	 */
	@FXML
	public void chooseDriverJar() {
		FileChooser fc = new FileChooser();
		fc.setSelectedExtensionFilter(new ExtensionFilter(I18N.get("tooltip.driver_jar_files"), "jar"));
		fc.setTitle(I18N.get("title.choose_jar"));
		File file = fc.showOpenDialog(App.STAGE_MAP.get(StageView.MAIN_VIEW));
		if(file != null) {
			config_database_driver_jar_path.setText(file.getAbsolutePath());
		}
	}
	
	/**
	 * 退出系统
	 * @author Frankle
	 * @date 2020年5月20日
	 */
	@FXML
	public void exit() {
		System.exit(0);
	}
	
	/**
	 * 测试连接
	 * @author Frankle
	 * @date 2020年5月20日
	 */
	@FXML
	public void testConnect() {
		Connection conn = null;
		try {
			dbType = config_database_type.getSelectionModel().getSelectedItem();
			if(dbType != null) {
				if(StringUtils.isBlank(config_database_url.getText())) {
					AlertUtils.showError(I18N.get("message.config_database_url_is_empty"));
					return;
				}
				
				driver = getSelectJDBCDriver(dbType);
				if(driver == null) {
					AlertUtils.showError(I18N.get("message.db_not_support"));
					return;
				}
				
				DriverManager.registerDriver(driver);
				
				conn = DriverManager.getConnection(config_database_url.getText().trim(), config_database_username.getText().trim(), config_database_password.getText().trim());
				if(conn != null) {
					AlertUtils.showMessage(I18N.get("message.connect_success"));
				} else {
					AlertUtils.showError(I18N.get("message.connect_fail"));
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if(conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
	/**
	 * 初始化全局配置
	 * @author Frankle
	 * @date 2020年5月21日
	 */
	@FXML
	public void initGlobalConfig() {
		config_global_activerecord.setSelected(gbCfg.isActiveRecord());
		config_global_basecolumnlist.setSelected(gbCfg.isBaseColumnList());
		config_global_baseresultmap.setSelected(gbCfg.isBaseResultMap());
		config_global_enablecache.setSelected(gbCfg.isEnableCache());
		config_global_fileoverride.setSelected(gbCfg.isFileOverride());
		config_global_open.setSelected(gbCfg.isOpen());
		config_global_kotlin.setSelected(gbCfg.isKotlin());
		config_global_swagger2.setSelected(gbCfg.isSwagger2());
		config_global_author.setText(gbCfg.getAuthor());
		config_global_controllername.setText(gbCfg.getControllerName());
		config_global_entityname.setText(gbCfg.getEntityName());
		config_global_mappername.setText(gbCfg.getMapperName());
		config_global_output.setText(gbCfg.getOutputDir());
		config_global_serviceimplname.setText(gbCfg.getServiceImplName());
		config_global_servicename.setText(gbCfg.getServiceName());
		config_global_xmlname.setText(gbCfg.getXmlName());
		tg_date_type.selectToggle(date_type_timepack);
		tg_id_type.selectToggle(id_type_auto);
	}
	
	/**
	 * 初始化包名配置
	 * @author Frankle
	 * @date 2020年5月21日
	 */
	@FXML
	public void initPackageConfig() {
		config_packageInfo_parent.setText(pkgCfg.getParent());
		config_packageInfo_module.setText(pkgCfg.getModuleName());
		config_packageInfo_entity.setText(pkgCfg.getEntity());
		config_packageInfo_controller.setText(pkgCfg.getController());
		config_packageInfo_service.setText(pkgCfg.getService());
		config_packageInfo_serviceimpl.setText(pkgCfg.getServiceImpl());
		config_packageInfo_mapper.setText(pkgCfg.getMapper());
		config_packageInfo_xml.setText(pkgCfg.getXml());
	}
	
	/**
	 * 初始化策略配置
	 * @author Frankle
	 * @date 2020年5月21日
	 */
	@FXML
	public void initStrategyConfig() {
		cfg_strategy_logic_delete_field.setText(stgCfg.getLogicDeleteFieldName());
		cfg_strategy_boolean_column_remove_is_prefix.setSelected(stgCfg.isEntityBooleanColumnRemoveIsPrefix());
		cfg_strategy_builder_mode.setSelected(stgCfg.isEntityBuilderModel());
		cfg_strategy_capital_mode.setSelected(stgCfg.isCapitalMode());
		cfg_strategy_column_constant.setSelected(stgCfg.isEntityColumnConstant());
		cfg_strategy_lombok_mode.setSelected(stgCfg.isEntityLombokModel());
		cfg_strategy_mapping_hyphen_style.setSelected(stgCfg.isControllerMappingHyphenStyle());
		cfg_strategy_restcontroller_style.setSelected(stgCfg.isRestControllerStyle());
		cfg_strategy_skip_view.setSelected(stgCfg.isSkipView());
		cfg_strategy_super_controller_class.setText(stgCfg.getSuperControllerClass());
		cfg_strategy_super_entity_class.setText(stgCfg.getSuperEntityClass());
		cfg_strategy_super_entity_columns.setText("");
		cfg_strategy_super_mapper_class.setText(stgCfg.getSuperMapperClass());
		cfg_strategy_super_service_class.setText(stgCfg.getSuperServiceClass());
		cfg_strategy_super_serviceimpl_class.setText(stgCfg.getSuperServiceImplClass());
		cfg_strategy_table_field_annotation.setSelected(stgCfg.isEntityTableFieldAnnotationEnable());
		cfg_strategy_table_prefix.setText("");
		cfg_strategy_version_field.setText(stgCfg.getVersionFieldName());
		
		naming_no_change.setUserData(NamingStrategy.no_change);
		naming_underline_to_camel.setUserData(NamingStrategy.underline_to_camel);
		
		column_naming_no_change.setUserData(NamingStrategy.no_change);
		column_naming_underline_to_camel.setUserData(NamingStrategy.underline_to_camel);
	}
	
	/**
	 * 初始化模板配置
	 * @author Frankle
	 * @date 2020年5月21日
	 */
	@FXML
	public void initTemplateConfig() {
		cfg_template_custom_template.selectedProperty().addListener(new ChangeListener<Boolean>() {

			@Override
			public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
				if(newValue) {
					cfg_template_controller.setDisable(false);
					cfg_template_entity.setDisable(false);
					cfg_template_entity_kt.setDisable(false);
					cfg_template_service.setDisable(false);
					cfg_template_serviceimpl.setDisable(false);
					cfg_template_mapper.setDisable(false);
					cfg_template_xml.setDisable(false);
					
					template_engine_velocity.setDisable(false);
					template_engine_freemarker.setDisable(false);
					template_engine_beelt.setDisable(false);
				} else {
					cfg_template_controller.setDisable(true);
					cfg_template_entity.setDisable(true);
					cfg_template_entity_kt.setDisable(true);
					cfg_template_service.setDisable(true);
					cfg_template_serviceimpl.setDisable(true);
					cfg_template_mapper.setDisable(true);
					cfg_template_xml.setDisable(true);
					template_engine_velocity.setDisable(true);
					template_engine_freemarker.setDisable(true);
					template_engine_beelt.setDisable(true);
				}
			}
		});
		
		cfg_template_custom_template.setSelected(false);
		
		template_engine_velocity.setUserData(TemplateEngine.VELOCITY);
		template_engine_freemarker.setUserData(TemplateEngine.FREEMARKER);
		template_engine_beelt.setUserData(TemplateEngine.BEETL);
	}
	
	/**
	 * 执行生成代码
	 * @author Frankle
	 * @date 2020年5月20日
	 */
	@FXML
	public void generateCode() {
		GlobalConfig global = new GlobalConfig();
		
		if(StringUtils.isNotBlank(config_global_output.getText())) {
			global.setOutputDir(config_global_output.getText().trim());
		}
		
		RadioButton dateType = (RadioButton)tg_date_type.getSelectedToggle();
		global.setDateType(DateType.valueOf(dateType.getUserData().toString()));
		
		RadioButton idType = (RadioButton)tg_id_type.getSelectedToggle();
		global.setIdType(IdType.valueOf(idType.getUserData().toString()));
		
		if(StringUtils.isNotBlank(config_global_author.getText())) {
			global.setAuthor(config_global_author.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_global_entityname.getText())) {
			global.setEntityName(config_global_entityname.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_global_controllername.getText())) {
			global.setControllerName(config_global_controllername.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_global_servicename.getText())) {
			global.setServiceName(config_global_servicename.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_global_serviceimplname.getText())) {
			global.setServiceImplName(config_global_serviceimplname.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_global_mappername.getText())) {
			global.setMapperName(config_global_mappername.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_global_xmlname.getText())) {
			global.setXmlName(config_global_xmlname.getText().trim());
		}
		
		global.setFileOverride(config_global_fileoverride.isSelected());
		global.setActiveRecord(config_global_activerecord.isSelected());
		global.setBaseColumnList(config_global_basecolumnlist.isSelected());
		global.setBaseResultMap(config_global_baseresultmap.isSelected());
		global.setEnableCache(config_global_enablecache.isSelected());
		global.setKotlin(config_global_kotlin.isSelected());
		global.setSwagger2(config_global_swagger2.isSelected());
		global.setOpen(config_global_open.isSelected());
		
		/*
		 * 数据源配置
		 */
		DataSourceConfig dataSource = new DataSourceConfig();
		
		if(StringUtils.isBlank(config_database_url.getText())) {
			AlertUtils.showError(I18N.get("message.config_database_url_is_empty"));
			return;
		}
		
		dbType = config_database_type.getSelectionModel().getSelectedItem();
		driver = getSelectJDBCDriver(dbType);
		
		if(driver == null) {
			AlertUtils.showError(I18N.get("message.db_not_support"));
			return;
		}
		dataSource.setUrl(config_database_url.getText().trim());
		dataSource.setDriverName(driver.getClass().getCanonicalName());
		dataSource.setUsername(config_database_username.getText().trim());
		dataSource.setPassword(config_database_password.getText().trim());
		dataSource.setDbType(dbType);
		
		if(StringUtils.isNotBlank(config_database_postgreSQL_schema.getText())) {
			dataSource.setSchemaName(config_database_postgreSQL_schema.getText().trim());
		}
		
		/*
		 * 包名配置
		 */
		PackageConfig packageInfo = new PackageConfig();
		
		if(StringUtils.isNotBlank(config_packageInfo_parent.getText())) {
			packageInfo.setParent(config_packageInfo_parent.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_packageInfo_module.getText())) {
			packageInfo.setModuleName(config_packageInfo_module.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_packageInfo_entity.getText())) {
			packageInfo.setEntity(config_packageInfo_entity.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_packageInfo_controller.getText())) {
			packageInfo.setController(config_packageInfo_controller.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_packageInfo_service.getText())) {
			packageInfo.setService(config_packageInfo_service.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_packageInfo_serviceimpl.getText())) {
			packageInfo.setServiceImpl(config_packageInfo_serviceimpl.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_packageInfo_mapper.getText())) {
			packageInfo.setMapper(config_packageInfo_mapper.getText().trim());
		}
		
		if(StringUtils.isNotBlank(config_packageInfo_xml.getText())) {
			packageInfo.setXml(config_packageInfo_xml.getText().trim());
		}
		
		/*
		 * 表名配置
		 */
		StrategyConfig strategy = new StrategyConfig();
		strategy.setCapitalMode(cfg_strategy_capital_mode.isSelected());
		strategy.setNaming((NamingStrategy)tg_naming.getSelectedToggle().getUserData());
		strategy.setColumnNaming((NamingStrategy)tg_column_naming.getSelectedToggle().getUserData());
		
		if(StringUtils.isNotBlank(cfg_strategy_exclude.getText())) {
			strategy.setExclude(cfg_strategy_exclude.getText().trim());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_include.getText())) {
			strategy.setInclude(cfg_strategy_include.getText().trim());
		}
		
		strategy.setSkipView(cfg_strategy_skip_view.isSelected());
		
		if(StringUtils.isNotBlank(cfg_strategy_field_prefix.getText())) {
			strategy.setFieldPrefix(cfg_strategy_field_prefix.getText());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_table_prefix.getText())) {
			strategy.setTablePrefix(cfg_strategy_table_prefix.getText().trim());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_super_controller_class.getText())) {
			strategy.setSuperControllerClass(cfg_strategy_super_controller_class.getText().trim());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_super_entity_class.getText())) {
			strategy.setSuperEntityClass(cfg_strategy_super_entity_class.getText().trim());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_super_entity_columns.getText())) {
			strategy.setSuperEntityColumns(cfg_strategy_super_entity_columns.getText().trim());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_super_service_class.getText())) {
			strategy.setSuperServiceClass(cfg_strategy_super_service_class.getText().trim());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_super_serviceimpl_class.getText())) {
			strategy.setSuperServiceImplClass(cfg_strategy_super_serviceimpl_class.getText().trim());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_super_mapper_class.getText())) {
			strategy.setSuperMapperClass(cfg_strategy_super_mapper_class.getText().trim());
		}
		
		strategy.setControllerMappingHyphenStyle(cfg_strategy_mapping_hyphen_style.isSelected());
		strategy.setEntityBooleanColumnRemoveIsPrefix(cfg_strategy_boolean_column_remove_is_prefix.isSelected());
		strategy.setEntityBuilderModel(cfg_strategy_builder_mode.isSelected());
		strategy.setEntityColumnConstant(cfg_strategy_column_constant.isSelected());
		strategy.setEntityLombokModel(cfg_strategy_lombok_mode.isSelected());
		strategy.setEntityTableFieldAnnotationEnable(cfg_strategy_table_field_annotation.isSelected());
		
		if(StringUtils.isNotBlank(cfg_strategy_logic_delete_field.getText())) {
			strategy.setLogicDeleteFieldName(cfg_strategy_logic_delete_field.getText().trim());
		}
		
		if(StringUtils.isNotBlank(cfg_strategy_version_field.getText())) {
			strategy.setVersionFieldName(cfg_strategy_version_field.getText().trim());
		}
		
		strategy.setRestControllerStyle(cfg_strategy_restcontroller_style.isSelected());
		
		TemplateConfig template = null;
		AbstractTemplateEngine engine = null;
		if(cfg_template_custom_template.isSelected()) {
			template = new TemplateConfig();
			
			if(StringUtils.isNotBlank(cfg_template_controller.getText())) {
				template.setController(cfg_template_controller.getText().trim());
			}
			
			if(StringUtils.isNotBlank(cfg_template_entity.getText())) {
				template.setEntity(cfg_template_entity.getText().trim());
			}
			
			if(config_global_kotlin.isSelected() && StringUtils.isNotBlank(cfg_template_entity_kt.getText())) {
				template.setEntityKt(cfg_template_entity_kt.getText().trim());
			}
			
			if(StringUtils.isNotBlank(cfg_template_service.getText())) {
				template.setMapper(cfg_template_service.getText().trim());
			}
			
			if(StringUtils.isNotBlank(cfg_template_serviceimpl.getText())) {
				template.setService(cfg_template_serviceimpl.getText().trim());
			}
			
			if(StringUtils.isNotBlank(cfg_template_mapper.getText())) {
				template.setServiceImpl(cfg_template_mapper.getText().trim());
			}
			
			if(StringUtils.isNotBlank(cfg_template_xml.getText())) {
				template.setXml(cfg_template_xml.getText().trim());
			}
			
			RadioButton rb = (RadioButton)tg_template_engine.getSelectedToggle();
			TemplateEngine te = (TemplateEngine)rb.getUserData();
			if(TemplateEngine.FREEMARKER.equals(te)) {
				engine = new FreemarkerTemplateEngine();
			} else if(TemplateEngine.BEETL.equals(te)) {
				engine = new BeetlTemplateEngine();
			} else {
				engine = new VelocityTemplateEngine();
			}
		}
		
		AutoGenerator generator = new AutoGenerator();
		generator.setGlobalConfig(global);
		generator.setDataSource(dataSource);
		generator.setPackageInfo(packageInfo);
		generator.setStrategy(strategy);
		
		if(cfg_template_custom_template.isSelected()) {
			generator.setTemplate(template);
		}
		
		if(engine != null) {
			generator.setTemplateEngine(engine);
		}
		
		lb_status.textProperty().bind(I18N.createStringBinding("message.generating"));
		generator.execute();
		
		lb_status.textProperty().bind(I18N.createStringBinding("message.generate_completed"));
		AlertUtils.showMessage(I18N.get("message.generate_code_success"));
	}
	
	private Driver getSelectJDBCDriver(DbType dbType) {
		Driver driver = null;
		
		showCustomDriverField(false);
		if(DbType.MYSQL.equals(dbType)) {
			try {
				driver = new com.mysql.cj.jdbc.Driver();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		} else if(DbType.DB2.equals(dbType)){
			driver = new com.ibm.db2.jcc.DB2Driver();
		} else if(DbType.DM.equals(dbType)){
			//暫不支持
		} else if(DbType.H2.equals(dbType)){
			driver = new org.h2.Driver();
		} else if(DbType.HSQL.equals(dbType)){
			driver = new org.hsqldb.jdbc.JDBCDriver();
		} else if(DbType.MARIADB.equals(dbType)){
			driver = new org.mariadb.jdbc.Driver();
		} else if(DbType.ORACLE.equals(dbType) || DbType.ORACLE_12C.equals(dbType)){
			driver = new oracle.jdbc.driver.OracleDriver();
		} else if(DbType.POSTGRE_SQL.equals(dbType)){
			driver = new org.postgresql.Driver();
		} else if(DbType.SQL_SERVER.equals(dbType) || DbType.SQL_SERVER2005.equals(dbType)){
			driver = new com.microsoft.sqlserver.jdbc.SQLServerDriver();
		} else if(DbType.SQLITE.equals(dbType)){
			driver = new org.sqlite.JDBC();
		} else if(DbType.KINGBASE_ES.equals(dbType)) {
			driver = new com.kingbase.Driver();
		} else if(DbType.XU_GU.equals(dbType)) {
			//暫不支持
		}else if(DbType.PHOENIX.equals(dbType)) {
			driver = new org.apache.phoenix.jdbc.PhoenixDriver();
		} else if(DbType.OTHER.equals(dbType)){
			showCustomDriverField(true);
			URLClassLoader classLoader = null;
			try {
				
				if(StringUtils.isBlank(config_database_driver_jar_path.getText().trim())) {
					AlertUtils.showError(I18N.get("message.driver_jar_path_is_empty"));
					return null;
				}
				
				if(StringUtils.isBlank(config_database_driver_class_name.getText().trim())) {
					AlertUtils.showError(I18N.get("message.driver_class_name_is_empty"));
					return null;
				}
				
				URL driverUrl = new URL("file:" + config_database_driver_jar_path.getText().trim());
				classLoader = new URLClassLoader(new URL[] { driverUrl }, Thread.currentThread().getContextClassLoader());
				Class<?> driverClass = classLoader.loadClass(config_database_driver_class_name.getText().trim());
				return (Driver) driverClass.getDeclaredConstructor().newInstance();
			} catch (Exception e) {
				AlertUtils.showError(e.getMessage());
			}
		} else {
			return null;
		}
		return driver;
	}
	
	/**
	 * 显示自定义数据库驱动选择
	 * @author Frankle
	 * @date 2020年5月25日
	 * @param isShow
	 */
	private void showCustomDriverField(boolean isShow) {
		if(isShow) {
			rc_driver_jar_path.setPrefHeight(ROW_HEIGHT);
			rc_driver_jar_path.setMinHeight(ROW_HEIGHT);
			
			rc_driver_class_name.setPrefHeight(ROW_HEIGHT);
			rc_driver_class_name.setMinHeight(ROW_HEIGHT);
		} else {
			rc_driver_jar_path.setPrefHeight(0);
			rc_driver_jar_path.setMinHeight(0);
			
			rc_driver_class_name.setPrefHeight(0);
			rc_driver_class_name.setMinHeight(0);
		}
		
		lb_config_database_driver_jar_path.setVisible(isShow);
		config_database_driver_jar_path.setVisible(isShow);
		btn_choose_driver_jar.setVisible(isShow);
		
		lb_config_database_driver_class_name.setVisible(isShow);
		config_database_driver_class_name.setVisible(isShow);
	}
	
	/**
	 * 显示PostgreSQL schema
	 * @author Frankle
	 * @date 2020年5月25日
	 * @param isShow
	 */
	private void showPostgreSchemaField(boolean isShow) {
		if(isShow) {
			rc_postgreSQL_schema.setPrefHeight(ROW_HEIGHT);
			rc_postgreSQL_schema.setMinHeight(ROW_HEIGHT);
		} else {
			rc_postgreSQL_schema.setPrefHeight(0);
			rc_postgreSQL_schema.setMinHeight(0);
		}
		
		lb_config_database_postgreSQL_schema.setVisible(isShow);
		config_database_postgreSQL_schema.setVisible(isShow);
	}
	
	/**
	 * 初始化选项配置
	 * @author Frankle
	 * @date 2020年5月25日
	 */
	public void initOptionConfig() {
		
	}
}
